// Copyright (c) 2008-2010, Arne Claus
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the 
// following conditions are met:
//
// - Redistributions of source code must retain the above copyright notice, this list of conditions and the following 
//   disclaimer.
// - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following 
//   disclaimer in the documentation and/or other materials provided with the distribution.
// - Neither the name Arne Claus nor the names of any contributors may be used to endorse or promote products
//   derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, 
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifndef __INCLUDED_CRL_CONTEXT_H_
#define __INCLUDED_CRL_CONTEXT_H_

#include "CRL_Defines.h"
#include "CRL_Camera.h"
#include "CBL_IdMap.h"

#include "CRL_BufferAtomic.h"
#include "CRL_ParameterAtomic.h"

#define FlagKeepColorTargetN(_Target) (CB_NS::RenderLib::IContext::FlagKeepColorTarget | (1 << ((_Target) + 16))) 

CB_SUBNAMESPACE_START(RenderLib)

class IContext : public IResource
{
public:
	
	enum ERegisterType
	{
		FloatRegister = 0,
		IntRegister,
		BoolRegister,
		NumRegisterTypes
	};
    
	#define ENUM_ITEM(_Name) _Name,
	enum EPrimitveType
	{
    	Invalid = 0,
		#include "CRL_PrimitiveTypesEnum.h"
    	NumPrimitiveTypes
	};
	#undef ENUM_ITEM
	
	static const char*  s_PrimitveTypeNames[NumPrimitiveTypes];
    
    static const uint32 FlagKeepDepthTarget          = 1 << 1; //!< Depth buffer will not change on activate
    static const uint32 FlagKeepColorTarget          = 1 << 2; //!< Keeps ALL colortargets if set alone.
                                                               //!  Use FlagKeepColorTargetN([0..15]) to keep specific targets
    static const uint32 FlagKeepVertexConstants      = 1 << 3; //!< Does not upload any context bound vertex constants
    static const uint32 FlagKeepFragmentConstants    = 1 << 4; //!< Does not upload any context bound fragment constants
	static const uint32 FlagRestoreVertexConstants   = 1 << 5; //!< Restores ALL vertex constants
    static const uint32 FlagRestoreFragmentConstants = 1 << 6; //!< Restores ALL fragment constants
	
public:
	
	virtual CCamera* GetCamera();
	virtual void SetCamera(CCamera& _rCamera);
	
	IdType GetContextId() const { return m_ContextId; }
	
public:

	virtual void SetVertexConstantBounds(ERegisterType _Register, uint16 _Start=0, uint16 _End=-1) = 0;
	virtual void SetFragmentConstantBounds(ERegisterType _Register, uint16 _Start=0, uint16 _End=-1) = 0;
	
    virtual void SetColorTarget(uint8 _Stream, CBufferAtomicPtr _BufferAtomic) = 0;
	virtual void SetDepthTarget(CBufferAtomicPtr _BufferAtomic) = 0;
    
	virtual CBufferAtomicPtr GetColorTarget(uint8 _Stream) = 0;
	virtual CBufferAtomicPtr GetDepthTarget() = 0;
	
public:
	
	virtual void Activate(uint32 _Flags=0) = 0;
    virtual void Render(EPrimitveType _PrimitiveType) = 0;
	
protected:
	
	friend class CContextFactory;
	
	struct SRegisterBlock
	{
		uint16 m_RecoveryStartIdx[NumRegisterTypes];
		uint16 m_RecoveryEndIdx[NumRegisterTypes];
		uint16 m_NumRegisters[NumRegisterTypes];
		
		Math::Float4* m_FloatRegister;
		Math::Int4*   m_IntRegister;
		Math::Bool4*  m_BoolRegister;
	};
	
	SRegisterBlock m_VertexShaderConstants;
	SRegisterBlock m_FragmentShaderConstants;
	
	IdType  m_ContextId;
	CCamera m_Camera;
};

typedef CResourcePtr<IContext> CContextPtr;

CB_SUBNAMESPACE_END

#endif